#include <memory>
#include "lisp.hpp"
//#include "lispcore.hpp"
#include "common.hpp"

namespace lisp {
using namespace std;

/*
template<typename T1, typename T2> core::cons cons(T1 first, T2 second)
{
    return core::cons(make_shared<var>(first),  make_shared<var>(second));
}
*/

var car(const core::cons& a)
{
    return *(a.car());
}
var car(const var& a)
{
    return car (std::get<core::cons>(a));
}

var cdr(const core::cons& a)
{
    return *(a.cdr());
}

var cdr(const var& a)
{
    return cdr (std::get<core::cons>(a));
}

std::string repr(const core::pointer& a_ptr)
{
    return repr(*a_ptr);
}

std::string repr(const core::cons& a_cons) 
{
    using namespace std;
    std::stringstream ss;
    using std::operator<<;
    ss  << std::string("(cons ")<<'\n'
        << common::indent(repr(a_cons.car()), 5)<<'\n'
        << common::indent(repr(a_cons.cdr()), 5)<<")"
        ;
    return ss.str();
}

std::string repr(const var& a_var)
{
    enum {T_NIL, T_INT, T_DOUBLE, T_STRING, T_CONS};
    switch (a_var.index())
    {
    case T_NIL: return common::repr(nil);
    case T_INT: return common::repr(std::get<T_INT>(a_var));
    case T_DOUBLE: return common::repr(std::get<T_DOUBLE>(a_var));   
    case T_STRING: return common::repr(std::get<T_STRING>(a_var));   
    case T_CONS: return repr(std::get<T_CONS>(a_var));
    }
    return "string repr(const var& a_var) Error";
}


int g(int a,int b)
{
    return a+b;
}
}//lisp::


int lisp::f(int a,int b){return a+b;}

template<typename T1, typename T2>
int lisp::ffff (T1 a,T2 b) 
{
    return a + b;
}

